`include "sdr_head.v"

module sdr_fsm(
    input                   clk,
    input                   soft_rst,
    input                   local_rdreq,
    input                   local_wrreq,
    input                   init_done,
    input                   ref_done,
    input                   read_done,
    input                   write_done,
    input       [24 : 0]    local_addr,
    input                   time_flag,
    input       [31 : 0]    local_wdata,
    input       [31 : 0]    rdata,
    output reg              local_ready,
    output reg              ref_time_en,
    output reg  [1  : 0]    mux_sel,
    output reg              ref_en,
    output reg              init_en,
    output reg              read_en,
    output reg              write_en,
    output reg  [31 : 0]    local_rdata,
    output reg  [31 : 0]    wdata,
    output reg  [24 : 0]    int_addr
);

    localparam  s0 = 3'd0;
    localparam  s1 = 3'd1;
    localparam  s2 = 3'd2;
    localparam  s3 = 3'd3;
    localparam  s4 = 3'd4;

    reg [2 : 0] state;

    always @(posedge clk)
    begin
        if (!soft_rst) begin
            init_en <= 1'b0;
            ref_en <= 1'b0;
            ref_time_en <= 1'b0;
            mux_sel <= `INIT_MUX;
            write_en <= 1'b0;
            read_en <= 1'b0;
            wdata <= 32'b0;
            local_rdata <= 32'b0;
            local_ready <= 1'b0;
            int_addr <= 25'b0;
            state <= s0;
        end
        else begin
            case (state)
                s0 : begin
                    if (!init_done) begin
                        init_en <= 1'b1;
                        state <= s0;
                    end
                    else begin
                        ref_en <= 1'b1;
                        init_en <= 1'b0;
                        mux_sel <= `REF_MUX;
                        local_ready <= 1'b1;
                        state <= s1;
                    end
                end
                s1 : begin
                    if (!ref_done)
                        state <= s1;
                    else begin
                        ref_en <= 1'b0;
                        ref_time_en <= 1'b1;
                        state <= s2;
                    end
                end
                s2 : begin
                    if (local_wrreq) begin
                        write_en <= 1'b1;
                        mux_sel <= `WR_MUX;
                        int_addr <= local_addr;
                        wdata <= local_wdata;
                        local_ready <= 1'b0;
                        state <= s3;
                    end
                    else if (local_rdreq) begin
                        read_en <= 1'b1;
                        mux_sel <= `RD_MUX;
                        int_addr <= local_addr;
                        local_ready <= 1'b0;
                        state <= s4;
                    end
                    else if (time_flag) begin
                        ref_en <= 1'b1;
                        mux_sel <= `REF_MUX;
                        ref_time_en <= 1'b0;
                        state <= s1;
                    end
                    else
                        state <= s2;
                end
                s3 : begin
                    if (write_done) begin
                        write_en <= 1'b0;
                        mux_sel <= `REF_MUX;
                        local_ready <= 1'b1;
                        state <= s2;
                    end
                    else
                        state <= s3;
                end
                s4 : begin
                    if (read_done) begin
                        read_en <= 1'b0;
                        mux_sel <= `REF_MUX;
                        local_ready <= 1'b1;
                        local_rdata <= rdata;
                        state <= s2;
                    end
                    else
                        state <= s4;
                end
                default : state <= s0;
            endcase
        end
    end

endmodule 